package com.cfweb.controller.app;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpSession;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.cfweb.api.ApplicationApi;
import com.cfweb.api.BasicInfoApi;
import com.cfweb.api.ServiceApi;
import com.cfweb.api.UserApi;
import com.cfweb.dao.CfAppMapper;
import com.cfweb.dao.CfAuditMapper;
import com.cfweb.dao.CfAuditServiceMapper;
import com.cfweb.dao.CfEnvironmentMapper;
import com.cfweb.dao.CfNullServiceInstanceMapper;
import com.cfweb.dao.CfServiceInstanceMapper;
import com.cfweb.dao.CfServiceMapper;
import com.cfweb.domain.CfApp;
import com.cfweb.domain.CfAudit;
import com.cfweb.domain.CfAuditExternal;
import com.cfweb.domain.CfAuditService;
import com.cfweb.domain.CfAuditServiceExample;
import com.cfweb.domain.CfAuditServiceTemp;
import com.cfweb.domain.CfEnvironment;
import com.cfweb.domain.CfService;
import com.cfweb.domain.CfServiceInstance;
import com.cfweb.util.ExtJSResponse;

@Service
@Path("/audit")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class AuditManagement {
	private String null_plan;
	private String null_planid;

	@Value("${null_plan}")
	public void setNull_plan(String null_plan) {
		this.null_plan = null_plan;
	}

	@Value("${null_planid}")
	public void setNull_planid(String null_planid) {
		this.null_planid = null_planid;
	}

	/**
	 * Logger
	 */
	private Logger logger = Logger.getLogger(AuditManagement.class);
	/**
	 * session
	 */
	@Autowired
	private HttpSession session;
	/**
	 * mapper
	 */
	@Autowired
	private CfAuditMapper cfAuditMapper;
	/**
	 * appMapper
	 */
	@Autowired
	private CfAppMapper caMapper;
	@Autowired
	private CfEnvironmentMapper cfEnvironmentMapper;
	@Autowired
	private CfAuditServiceMapper cfAuditServiceMapper;
	@Autowired
	private CfServiceMapper cfServiceMapper;
	@Autowired
	private CfServiceInstanceMapper cfServiceInstanceMapper;
	@Autowired
	private CfNullServiceInstanceMapper cfNullServiceInstanceMapper;

	@Path("/listall")
	@GET
	public ExtJSResponse listall() throws Exception {
		List<CfAuditExternal> result = cfAuditMapper.getAll();
		logger.info(result.size());
		return ExtJSResponse.successResWithData(result);
	}

	@Path("/getone")
	@GET
	public ExtJSResponse list(@QueryParam("id") int auditId) throws Exception {
		Map<String, Object> resMap = new HashMap<String, Object>();
		CfAudit cfaudit = cfAuditMapper.selectByPrimaryKey(auditId);
		resMap.put("name", cfaudit.getAppName());
		resMap.put("memory", cfaudit.getMemory());
		resMap.put("instances", cfaudit.getInstance());
		// put运行时环境
		CfEnvironment env = cfEnvironmentMapper.selectByPrimaryKey(cfaudit.getEnvId());
		resMap.put("env", env.getEnvName());
		resMap.put("org", cfaudit.getOrg());
		resMap.put("space", cfaudit.getSpace());
		resMap.put("domain", cfaudit.getDomain());

		// 获取内存使用量
		BasicInfoApi.getMemoryServiceByOrgName(resMap, session, cfaudit.getOrg());
		// 获取service
		CfAuditServiceExample cse = new CfAuditServiceExample();
		cse.createCriteria().andAuditIdEqualTo(cfaudit.getId());

		List<CfAuditService> cfauditServiceList = cfAuditServiceMapper.selectByExample(cse);
		List<CfAuditServiceTemp> stoList = new ArrayList<CfAuditServiceTemp>();
		if (cfauditServiceList != null) {
			for (CfAuditService cas : cfauditServiceList) {
				CfAuditServiceTemp cst = new CfAuditServiceTemp();
				// 设置service的名称
				CfService cs = cfServiceMapper.selectByPrimaryKey(cas.getServiceId());

				int createOrSelect = cas.getType();
				if (createOrSelect == 0) {
					CfServiceInstance csi = cfServiceInstanceMapper.selectByPrimaryKey(cas.getServiceInstanceId());
					cst.setServiceInstanceName(csi.getServiceInstanceName());
					cst.setType("select");
				} else if (createOrSelect == 1) {
					cst.setType("create");
					cst.setServiceSize("small");
				} else if (createOrSelect == 2) {
					cst.setType("create");
					cst.setServiceSize("medium");
				} else if (createOrSelect == 3) {
					cst.setType("create");
					cst.setServiceSize("larget");
				}
				cst.setServiceName(cs.getSerName());
				cst.setServiceId(cs.getId());
				stoList.add(cst);
			}
			resMap.put("stoList", stoList);
		}

		return ExtJSResponse.successResWithData(resMap);
	}

	private void createService(String whichService, String serviceName, String servicePlan, String space_guid,
			String org, String space, CfAuditService service, String appUuid) throws Exception {
		if (!serviceName.equals("") && !servicePlan.equals("")) {
			// 获取planid
			String planid = ServiceApi.getGervicePlanGuid(session, serviceName, servicePlan, space_guid);
			// 获取 服务实例名称
			String instanceName = whichService + "_" + ""
					+ ServiceManagement.produceServiceName(ServiceManagement.SERVICE_INSTANCE_NAME_LENGTH);
			// 创建 服务实例
			boolean flag = ServiceApi.createServiceInstanceByOrgAndSpace(session, org, space, serviceName, planid,
					instanceName, true);
			if (flag) {
				// 创建成功后，应该写入到数据库中。
				CfServiceInstance serviceIns = new CfServiceInstance();
				serviceIns.setCreateTime(new Date());
				serviceIns.setService(serviceName);
				serviceIns.setPlan(servicePlan);
				serviceIns.setPlanId(planid);
				serviceIns.setUpdateTime(new Date());
				serviceIns.setServiceInstanceName(instanceName);
				serviceIns.setOrg(org);
				serviceIns.setSpace(space);
				serviceIns.setServiceTypeId(service.getServiceId());
				serviceIns.setState(2);
				// sleep 1s，确保数据写入到数据库中
				Thread.sleep(1000);
				ServiceApi.getHostPortUser(serviceIns);
				// 插入到数据库
				cfServiceInstanceMapper.insert(serviceIns);
				if (service.getType() == 2) {
					System.out.println("创建一个空服务");
					ServiceApi.createNullService(cfNullServiceInstanceMapper, instanceName, session, org, space, 1,
							null_plan, null_planid);
				} else if (service.getType() == 3) {
					System.out.println("创建2个空服务");
					ServiceApi.createNullService(cfNullServiceInstanceMapper, instanceName, session, org, space, 2,
							null_plan, null_planid);
				}
				ApplicationApi.bindService(appUuid, instanceName, session);
			}
		}
	}

	// class CreateServiceThread extends Thread {
	// private CfAuditService service;
	//
	// private String whichService;
	// private String serviceName;
	// private String servicePlan;
	// private String space_guid;
	// private String org;
	// private String space;
	// private String appUuid;
	//
	// public CreateServiceThread(CfAuditService service, String whichService,
	// String serviceName, String servicePlan,
	// String space_guid, String org, String space, String appUuid) {
	// super();
	// this.service = service;
	// this.whichService = whichService;
	// this.serviceName = serviceName;
	// this.servicePlan = servicePlan;
	// this.space_guid = space_guid;
	// this.org = org;
	// this.space = space;
	// this.appUuid = appUuid;
	// }
	//
	// @Override
	// public void run() {
	//
	// }
	//
	// }

	@Path("/agree")
	@POST
	@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
	public ExtJSResponse agree(@QueryParam("id") int id, @FormParam("mysql.service") final String mysqlService,
			@FormParam("mysql.plan") final String mysqlPlan, @FormParam("oracle.service") final String oracleService,
			@FormParam("oracle.plan") final String oraclePlan, @FormParam("redis.service") final String redisService,
			@FormParam("redis.plan") final String redisPlan,
			@FormParam("rabbitmq.service") final String rabbitmqService,
			@FormParam("rabbitmq.plan") final String rabbitmqPlan) throws Exception {
		CfAudit cfaudit = cfAuditMapper.selectByPrimaryKey(id);
		if (cfaudit == null) {
			return ExtJSResponse.successResWithData("失败，id不存在");
		}
		String org = cfaudit.getOrg();
		String space = cfaudit.getSpace();
		String appName = cfaudit.getAppName();
		String domain = cfaudit.getDomain();
		List<String> uri = new ArrayList<String>();
		uri.add(appName + "." + domain);

		Map<String, Object> params = new HashMap<String, Object>();
		params.put("name", cfaudit.getAppName());
		params.put("memory", Integer.valueOf(cfaudit.getMemory()));
		params.put("instances", Integer.valueOf(cfaudit.getInstance()));
		String space_guid = UserApi.get_space_id(session, org, space);
		params.put("space_guid", space_guid);
		String buildpack = cfEnvironmentMapper.selectByPrimaryKey(cfaudit.getEnvId()).getEnvName();
		params.put("buildpack", buildpack);
		params.put("disk_quota", 1024);
		if (buildpack.startsWith("clr_") || buildpack.toLowerCase().indexOf("net") != -1) {
			logger.info("choose .net app");
			params.put("stack_id", ApplicationApi.getStackUUID("windows2012", session));
		}
		String appUuid = null;
		try {
			appUuid = ApplicationApi.createApplication(params, session);
		} catch (Exception e) {
			return ExtJSResponse.successResWithData("创建失败，域名已使用");
		}
		try {
			ApplicationApi.updateApplicationUrls(appUuid, org, space, uri, session);
		} catch (Exception e) {
			ApplicationApi.deleteApp(appUuid, session);
			return ExtJSResponse.successResWithData("创建失败，域名已使用");
		}
		CfApp cfApp = new CfApp(appName, Integer.valueOf(cfaudit.getEnvId()), org, space, cfaudit.getTemplateId(),
				appUuid);
		caMapper.insertSelective(cfApp);

		File file = new File(cfaudit.getFileUrl());
		ApplicationApi.uploadAppBit(cfApp, file, session);
		file.delete();
		// 不进行启动，让用户来启动
		// ApplicationApi.startApplication(appUuid, session);
		// 获取audit对应的服务
		CfAuditServiceExample c1 = new CfAuditServiceExample();
		c1.createCriteria().andAuditIdEqualTo(cfaudit.getId());
		List<CfAuditService> services = cfAuditServiceMapper.selectByExample(c1);
		for (CfAuditService service : services) {
			if (service.getServiceInstanceId() == 0) {
				if (service.getType() != 0) {
					// 得到该服务对应的服务名称，比如mysql对应的是MySql
					String whichService = cfServiceMapper.selectByPrimaryKey(service.getServiceId()).getSerName();
					// 如果服务名称等于mysql
					if (whichService.toLowerCase().equals("mysql")) {
						createService(whichService, mysqlService, mysqlPlan, space_guid, org, space, service, appUuid);
					}
					// 如果服务名称等于redis
					else if (whichService.toLowerCase().equals("redis")) {
						createService(whichService, redisService, redisPlan, space_guid, org, space, service, appUuid);
					}
					// 如果服务名称等于rabbitmq
					else if (whichService.toLowerCase().equals("rabbitmq")) {
						createService(whichService, rabbitmqService, rabbitmqPlan, space_guid, org, space, service,
								appUuid);
					}
				}
			}
			// 与serviceInstanceId的服务进行绑定
			else if (service.getServiceInstanceId() != 0) {
				String serviceName = cfServiceInstanceMapper.selectByPrimaryKey(service.getServiceInstanceId())
						.getServiceInstanceName();

				ApplicationApi.bindService(appUuid, serviceName, session);
			}
		}

		CfAuditServiceExample cfAuditServiceExample = new CfAuditServiceExample();
		cfAuditServiceExample.createCriteria().andAuditIdEqualTo(id);
		cfAuditServiceMapper.deleteByExample(cfAuditServiceExample);
		cfAuditMapper.deleteByPrimaryKey(id);
		return ExtJSResponse.successResWithData("创建成功");
	}

	@Path("/disagree")
	@GET
	public ExtJSResponse disagree(final @QueryParam("id") Integer id) throws Exception {
		CfAudit record = cfAuditMapper.selectByPrimaryKey(id);
		if (record == null) {
			return ExtJSResponse.errorResWithMsg("数据不存在");
		}
		record.setState(1);
		int result = cfAuditMapper.updateByPrimaryKey(record);
		if (result != 1) {
			return ExtJSResponse.errorResWithMsg("更新失败");
		}
		return ExtJSResponse.successResWithData("更新成功");
	}

	/**
	 * 删除待审核的应用
	 * 
	 * @param id
	 * @return
	 */
	@Path("/delete")
	@GET
	public ExtJSResponse delete(@QueryParam("id") int id) {
		CfAuditServiceExample cfAuditServiceExample = new CfAuditServiceExample();
		cfAuditServiceExample.createCriteria().andAuditIdEqualTo(id);
		cfAuditServiceMapper.deleteByExample(cfAuditServiceExample);

		File file = new File(cfAuditMapper.selectByPrimaryKey(id).getFileUrl());
		file.delete();
		cfAuditMapper.deleteByPrimaryKey(id);

		return ExtJSResponse.successResWithData("删除成功");
	}
}
